import { AfterContentChecked, AfterContentInit, Component, ContentChild, Input, OnInit } from '@angular/core';

import { Hero, LoggerService, ComponentBase } from '../share';

@Component({
    selector: 'my-child',
    template: '<input [(ngModel)]="hero">'
})
export class ChildComponent extends ComponentBase {
    @Input()
    hero = '';
}

@Component({
    selector: 'after-content',
    template: `
    <div>-- projected content begins --</div>
      <ng-content></ng-content>
    <div>-- projected content ends --</div>`
    + `
    <p *ngIf="comment" class="comment">
      {{comment}}
    </p>
  `
})
export class AfterContentComponent extends ComponentBase implements OnInit, AfterContentChecked, AfterContentInit {
    private prevHero = '';
    comment = '';

    // Query for a CONTENT child of type `ChildComponent`
    @ContentChild(ChildComponent) contentChild: ChildComponent;

    constructor(private logger: LoggerService) {
        super();
        this.logIt('AfterContent constructor');
    }

    ngOnInit() {
        super.ngOnInit();
        this.logIt('ngOnInit');
    }

    ngAfterContentInit() {
        super.ngAfterContentInit();

        // contentChild is set after the content has been initialized
        this.logIt('AfterContentInit');
        this.doSomething();
    }

    ngAfterContentChecked() {
        super.ngAfterContentChecked();

        // contentChild is updated after the content has been checked
        if (this.prevHero === this.contentChild.hero) {
            this.logIt('AfterContentChecked (no change)');
        } else {
            this.prevHero = this.contentChild.hero;
            this.logIt('AfterContentChecked');
            this.doSomething();
        }
    }

    // This surrogate for real business logic sets the `comment`
    private doSomething() {
        this.comment = this.contentChild.hero.length > 10 ? `That's a long name` : '';
    }

    private logIt(method: string) {
        let child = this.contentChild;
        let message = `${method}: ${child ? child.hero : 'no'} child content`;
        this.logger.log(message);
    }
    // ...
}


@Component({
    selector: 'after-content-parent',
    template: `
  <div class="parent">
    <h2>AfterContent</h2>

    <div *ngIf="show">` +
    `<after-content>
        <my-child [hero]="newHero"></my-child>
      </after-content>`
    + `</div>

    <h4>-- AfterContent Logs --</h4>
    <p><button (click)="reset()">Reset</button></p>
    <div *ngFor="let msg of logs">{{msg}}</div>
  </div>
  `,
    styles: ['.parent {background: burlywood}'],
    providers: [LoggerService]
})
export class AfterContentParentComponent extends ComponentBase {
    logs: string[];
    show = true;
    newHero = 'Jupige is the hero, now!';

    constructor(private logger: LoggerService) {
        super();
        this.logs = logger.logs;
    }

    reset() {
        this.logs.length = 0;
        // quickly remove and reload AfterContentComponent which recreates it
        this.show = false;
        this.logger.tick_then(() => this.show = true);
    }
}


/*
     Remark:
        afterContents关心的是ContentChildren，ng-content配套的。
        1. ngContent里面的内容在constructor之后就已经存在ngContent的内容投影实例,
            但未初始化，直至,AfterContentInit，这时内容投影才初始化完毕。
        2. 当使用ngIf,如果为false，则DOM元素会被移除，触发Ondestroy;
            为true，则重新生成(new)DOM元素对应的Component实例。---> 是否可以考虑通过样式来隐藏显示？
        3. ngIf存在时，带有ngIf的Component的构造函数不是立即调用(紧跟着父Component的构造函数)，
            而是在ngContentChecked之后再初始化。
            猜测是ngIf的参数需要在父Component初始化完之后才能决定是否加载该Component导致的。

        Q: 什么是ContentChildren、ViewChildren
        A: ComponentA, 它的Template里面的标签就是ViewChildren
           当你使用它时，<componentA>some thing</componentA>,标签之间的内容就是ContentChildren
*/
